#include "MqttService.h"

void MqttService::nonStopLoop(MqttService *p)
{
    while (true)
    {
        usleep(1000);
        if (p->uuidConnectionMap.empty())
            continue;
        for (auto kv : p->uuidConnectionMap)
        {
            if (!kv.second->looping)
            {
                p->threadPool->enqueue(MqttConnection::loop, kv.second);
            }
        }
    }
}
MqttService::MqttService()
{
    threadPool = new ThreadPool(4);
    threadPool->enqueue(MqttService::nonStopLoop, this);
}
MqttConnection *MqttService::addConnection(const std::string &name,
                                           const std::string &address,
                                           bool enable,
                                           int port,
                                           const std::string &uuid,
                                           const std::string &userName,
                                           const std::string &password)
{
    if (nameConnectionMap.count(name) || uuidConnectionMap.count(uuid))
    {
        return nullptr;
    }
    else
    {
        MqttConnection *p = new MqttConnection(&nameConnectionMap, name, address, enable, port, userName, password);
        if (uuid == "")
            p->uuid = sole::uuid4().str();
        else
            p->uuid = uuid;
        uuidConnectionMap.emplace(uuid, p);
        return p;
    }
}
std::string MqttService::genUUID()
{
    return sole::uuid4().str();
}
MqttConnection *MqttService::getConnectionByName(const std::string &name)
{
    try
    {
        return nameConnectionMap.at(name);
    }
    catch (...)
    {
        return nullptr;
    }
}
MqttConnection *MqttService::getConnectionByUUID(const std::string &uuid)
{
    try
    {
        return uuidConnectionMap.at(uuid);
    }
    catch (...)
    {
        return nullptr;
    }
}
void MqttService::removeConnectionByName(const std::string &name)
{
    try
    {
        MqttConnection *p = nameConnectionMap.at(name);
        nameConnectionMap.erase(name);
        uuidConnectionMap.erase(p->uuid);
        delete p;
    }
    catch (...)
    {
    }
}
void MqttService::removeConnectionByUUID(const std::string &uuid)
{
    try
    {
        MqttConnection *p = uuidConnectionMap.at(uuid);
        nameConnectionMap.erase(p->getName());
        uuidConnectionMap.erase(uuid);
        delete p;
    }
    catch (...)
    {
    }
}
Json::Value MqttService::getConnectionJson(const std::string &uuid)
{

    Json::Value jValue;
    if (!uuidConnectionMap.count(uuid))
        return jValue;
    MqttConnection *p = uuidConnectionMap.at(uuid);
    jValue["id"] = uuid;
    jValue["connectionName"] = p->getName();
    jValue["connectionStatus"] = p->getStatus();
    jValue["prefix"] = "mqtt://";
    jValue["address"] = p->getAddress();
    jValue["port"] = p->getPort();
    jValue["enable"] = p->isEnable();
    jValue["userName"] = p->getUserName();
    jValue["password"] = p->getPassword();
    jValue["remarks"] = p->remarks;
    return jValue;
}
Json::Value MqttService::getConnectionList()
{
    Json::Value jValue(Json::arrayValue);
    for (std::pair<std::string, MqttConnection *> kv : uuidConnectionMap)
    {
        jValue[jValue.size()] = getConnectionJson(kv.first);
    }
    return jValue;
}
MqttService::~MqttService()
{
    delete threadPool;
}
MqttService &MqttService::getInstance()
{
    static MqttService mqttService;
    return mqttService;
}